今天要主要來分享一下特性描述器。
在 ES5 之前 JS 無法讓你判定該物件特性的"特徵",
意思是說你沒辦法知道他是不是 read-only 之類的。
至於以前怎麼知道他是不是...
書中沒有特別提道,
感覺只能用猜的或是直接嘗試(我自己猜的)。
但是在 ES5 增加了一個功能叫做特性描述器 (property descriptor)。
const obj = {
a: 17
};
Object.getOwnPropertyDescriptor(obj,"a");
/*
{
value: 17,
writable: true,
enumerable: true,
configurable: true
}
*/
由上述的範例可以看到他除了 value
之外,他還有三個特徵。
那我們該如何修改這特徵?
可以使用 Object.defineProperty(..)
新增或是修改現有的特性。
要注意的是如果是修改現有的特性的話他要是可配置的(configurable)。
const obj = {}; // 給個空物件
Object.defineProperty(obj,"a",{
value: 17,
writable: true,
enumerable: true,
configurable: true
});
obj.a; // 17 出現啦~
接著我們針對這三個特徵來一一說明。
這部分很簡單,這邊就是單純你可以決定你能否變更一個特性的值。
const obj = {}; // 給個空物件
Object.defineProperty(obj,"a",{
value: 17,
writable: false,
enumerable: true,
configurable: true
});
obj.a = 123;
obj.a; // 17 Ops 還是原本的 17
如果你不是在嚴格模式下,你的更改值這動作會直接被吃掉,他也不會跟你說更改失敗,
但是反之你如果在嚴格模式下,他會直接噴爆你給你個 TypeError
並且很貼心的跟你說這是個不可寫入的特性。
這個馬上之後會提到這邊先提一點點,這部分主要會影響到的是 for .. in 迴圈 等等之類的。
來個範例
const obj = {
name: 'robin'
}
Object.defineProperty(obj,"age",{
value: 16,
writable: true,
enumerable: true,
configurable: true
});
for(let targetProp in obj){
console.log(targetProp);
};
// name
// age
Object.defineProperty(obj,"age",{
value: 16,
writable: true,
enumerable: false, // 把 age 改成不可列舉
configurable: true
});
for(let targetProp in obj){
console.log(targetProp);
};
// name
// 啊... 看不到 age 了
可配置就是剛剛提到的Object.defineProperty(..)
,能不能修改就是看這個啦。
const obj = {
a: 17
}
Object.defineProperty(obj,"a",{
value: 16,
writable: true,
enumerable: true,
configurable: false // 設定不可改
});
Object.defineProperty(obj,"a",{
value: 18,
writable: true,
enumerable: true,
configurable: true // 設定可改
}); // TypeError
這邊不管你是不是嚴格模式都會噴你 TypeError
,那如果從 false 想把它改回來怎麼辦...?
答案是你沒有回頭路xDD
那如果我直接刪掉它這個特性呢?
const obj = {
a: 17
}
delete obj.a;
obj.a; // undefined 不見了
Object.defineProperty(obj,"a",{
value: 16,
writable: true,
enumerable: true,
configurable: false // 設定不可改
});
obj.a; // 16
delete obj.a;
obj.a; // 16 砍不掉啊啊啊啊
以上是今天的內容,
也認識到了特性描述器這神奇的東東。
感謝您的收看我們明天見~
你所不知道的 JS|範疇與 Closures,this 與物件原型 (You Don't Know JS: this & Object Prototypes))